package com.lvmama.pangolin.matchcontroller;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lvmama.pangolin.busi.config.ConfigManager;
import com.lvmama.pangolin.common.Constant;
import com.lvmama.pangolin.common.ExportCSVUtils;
import com.lvmama.pangolin.common.MD5Util;
import com.lvmama.pangolin.common.StringTools;
import com.lvmama.pangolin.common.UUIDUtil;
import com.lvmama.pangolin.controller.BaseController;
import com.lvmama.pangolin.entity.match.MatchTicketCommodity;
import com.lvmama.pangolin.entity.match.MatchTicketCommodityRel;
import com.lvmama.pangolin.match.service.MatchTicketCommodityRelService;
import com.lvmama.pangolin.match.service.MatchTicketCommodityService;
import com.lvmama.pangolin.util.CommodityMatchUtil;

import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* Created by zhoutianqi on 2017/07/25.
*/
@Controller
@RequestMapping("/match/ticket/commodity")
public class MatchTicketCommodityController extends BaseController{
	private Logger logger = Logger.getLogger(getClass());
    @Autowired
    private MatchTicketCommodityService matchTicketCommodityService;
    @Autowired
    private MatchTicketCommodityRelService matchTicketCommodityRelService;
    
    @Autowired
    private CommodityMatchUtil commodityMatchUtil;
    
    @ResponseBody
    @RequestMapping("/cleanRelevance")
    public Map<String,String> cleanRelevance(HttpServletRequest request) {
    	Map<String,String> result = new HashMap<>();
    	try {
    		Map<String,String> paramMap = new HashMap<>();
    		paramMap.put("userId", getCurrentUser(request).getId());
			matchTicketCommodityService.deleteByMap(paramMap);
			result.put("Success","数据清除成功！");
		} catch (Exception e) {
			result.put("errorMessage","数据清除失败！");
		}
    	return result;
    }
    
    @ResponseBody
    @RequestMapping("/delete")
    public Map<String,String> delete(String id) {
    	Map<String,String> result = new HashMap<>();
    	try {
			matchTicketCommodityService.deleteById(id);
	    	result.put("Success","删除数据成功！");
		} catch (Exception e) {
			result.put("errorMessage","删除数据失败！");
		}
    	return result;
    }
    
    @RequestMapping("/addOrUpdate")
    public String add(HttpServletRequest request, MatchTicketCommodity param) {
    	boolean operType = false;//默认false-更新
    	if(!StringTools.isValid(param.getId())){
    		operType = true;//新增
    		param.setId(MD5Util.encode(UUIDUtil.getUUIDKey()+param.getCommodityId()));
    		param.setUserId(getCurrentUser(request).getId());
    		param.setCreateTime(new Date());
    	}
    	commodityMatchUtil.preHandelMatchTicketCommodity(param);
    	if(operType){
    		matchTicketCommodityService.save(param);
    	}else{
    		matchTicketCommodityService.update(param);
    	}
    	return "redirect:/match/ticket/commodity/list";
    }
	@RequestMapping("/list")
    public String list(Model model,MatchTicketCommodity param, @RequestParam(defaultValue = "1") Integer page,HttpServletRequest request) {
		List<MatchTicketCommodity> listWithLvmm = new ArrayList<>();
		//已经自动关联的商品数据id  uuid
		Map<String,Object> extraInfoParamMap = new HashMap<>();
		List<String> isList = new ArrayList<>();
		//List<String> companyList = new ArrayList<>();
		//查询参数
		Map<String,String> paramMap = new HashMap<>();
		paramMap.put("userId", getCurrentUser(request).getId());
		if(param!=null){
			if(StringTools.isValid(param.getCompanyCode())){
				paramMap.put("companyCode", param.getCompanyCode().trim());
				model.addAttribute("companyCodeOfSearch",param.getCompanyCode().trim());
			}
			if(StringTools.isValid(param.getProductName())){
				paramMap.put("productName", param.getProductName().trim());
				model.addAttribute("productNameOfSearch",param.getProductName().trim());
			}
			if(StringTools.isValid(param.getCommodityName())){
				paramMap.put("commodityName", param.getCommodityName().trim());
				model.addAttribute("commodityNameOfSearch",param.getCommodityName().trim());
			}
			if(StringTools.isValid(param.getCommodityId())){
				paramMap.put("commodityId", param.getCommodityId().trim());
				model.addAttribute("commodityIdOfSearch",param.getCommodityId().trim());
			}
		}
		
		paramMap.put("refuseCompanyCode", Constant.COMMODITY_AUTO_MATCH_LMM_COMPANY_CODE);
		PageHelper.startPage(page, 10);
		List<MatchTicketCommodity> list = matchTicketCommodityService.findListByMap(paramMap);
        PageInfo<MatchTicketCommodity> pageInfo = new PageInfo<MatchTicketCommodity>(list);
        
        for(MatchTicketCommodity item:list){
        	if(StringTools.isValid(item.getLvCommodityId())){
        		isList.add(item.getId());
        	}
        }
        if(isList.size()>0){
        	extraInfoParamMap.put("idList", isList);
        	extraInfoParamMap.put("userId", getCurrentUser(request).getId());
        	listWithLvmm = matchTicketCommodityService.findExtraInfo(extraInfoParamMap);
        	for(MatchTicketCommodity item2:listWithLvmm){
        		for(MatchTicketCommodity item3:list){
        			if(item2.getId().equals(item3.getId())){
        				item3.setLvCommodityName(item2.getLvCommodityName());
        				item3.setLmmPrice(item2.getLmmPrice());
        			}
        			continue;
        		}
        	}
        	
        }
        model.addAttribute("matchTicketCommodityList",list);
		model.addAttribute("page",pageInfo);
        return "match/commodityMatch";
    }
    
	@RequestMapping("/export")
    public void exportData(HttpServletResponse response,HttpServletRequest request) throws IOException{
    	String curremtUserId = getCurrentUser(request).getId();
    	Map<String, String> paramMap = new HashMap<>();
		paramMap.put("userId", curremtUserId);
		paramMap.put("exportExcelFlag", "true");//仅仅只是标记
    	List<MatchTicketCommodity> companyList = matchTicketCommodityService.findListByMap(paramMap);
	   // 生成提示信息，
	   response.setContentType("application/octet-stream");
	   // 进行转码，使其支持中文文件名
	   String fileName = java.net.URLEncoder.encode("商品自动配置监控表", "UTF-8");
	   response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".csv");
	   BufferedWriter bf = new BufferedWriter(new OutputStreamWriter(response.getOutputStream(), "gbk"),1024);
	   
	  String[] headers={"监控编号","采集页网址","监控平台","监控景区","省份","城市","商品ID","商品名称","价格","驴妈妈对应商品ID","支付方式","是否在线"};
	   Field[] fields=getFields(headers);
	   ExportCSVUtils<MatchTicketCommodity> exportCSVUtils = new ExportCSVUtils<MatchTicketCommodity>();
	   try {
		   logger.info("商品自动配置监控表导出数据条数:"+companyList.size()+"条");
		   exportCSVUtils.exportCSV(headers, fields, companyList, bf, "yyyy-MM-dd HH:mm:ss");
	   }
	   catch (Exception e) {
	       e.printStackTrace();
	   }
		
	}
    
    @ResponseBody
    @RequestMapping("/importExcel")
    public Map<String, String> importExcel(MultipartFile  file,HttpServletResponse response,HttpServletRequest request) {
    	logger.info("开始校验数据！>>>>>>>>>>>>>>>"+Thread.currentThread().getId());
    	
    	
    	Map<String, String> result = new HashMap<String, String>();
		InputStream is=null;
		int status = 0;//
		try {
			//转换成输入流  
	        is = file.getInputStream();  
	        //得到excel  
	        Workbook workbook = Workbook.getWorkbook(is);
	        //得到sheet  
	        Sheet[] sheets = workbook.getSheets();
	        //校验当前sheet标题是否符合规范
	        if(!checkExcelHead(sheets,result)){
	        	result.put("errorMessage","数据格式不正确，请修正后重新导入");
	        	closeInputStream(is);
	        	return result;
	        }
	        insertData(is, sheets, request);
	        logger.info("返回录入信息！>>>>>>>>>>>>>>>"+Thread.currentThread().getId());
	        
		} catch (Exception e) {
			result.put("errorMessage","导入Excel异常！");
			status = 4;
		}
		if(status==0){
			result.put("Success","数据导入成功！");
		}
        return result;
    }
    
    
    
    
    /**
     * 校验Excel头部数量是否对等，头部名称是否符合规范要求
    */
	public boolean checkExcelHead(Sheet[] sheets,Map<String, String> result){
    	String[] headRole = Constant.COMMODITY_AUTO_MATCH_EXCEL_ROLE.split(";");
    	for(Sheet sheet:sheets){
    		//得到列数  
	        int colsNum = sheet.getColumns();
	        if(colsNum != headRole.length){
	    		result.put("sheetmessage", "Sheet单元格表头格式不匹配，表头应该为："+Constant.COMMODITY_AUTO_MATCH_EXCEL_ROLE);
	    		return false;
	    	}
	    	for(int i=0;i<colsNum;i++){
	    		String head = sheet.getCell(i, 0).getContents();
	    		if(!head.equals(headRole[i])){
	    			result.put("sheetmessage", "Sheet单元格表头格式不匹配，Sheet表头应该为："+Constant.COMMODITY_AUTO_MATCH_EXCEL_ROLE);
	    			return false;
	    		}
	    	}
    	}
    	
    	return true;
    }
	
    
    
    private void closeInputStream(InputStream is){
    	if(is != null){
    		try {
				is.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    }
    private void insertData(InputStream is, Sheet[] sheets, HttpServletRequest request){
    	//商品总个数
    	int dataTotalNumber = 0;
    	//重复数据删除个数
    	int deletenumber = 0;
    	long systemTime = System.currentTimeMillis();
    	logger.info("开始导入数据！>>>>>>>>>>>>>>>"+Thread.currentThread().getId());
    	ConfigManager config = ConfigManager.getInstance();
    	int maxSize = Integer.parseInt(config.getParamValue("COMMODITY_AUTO_MATCH_MAX_SIZE", "COMMODITY_AUTO_MATCH_MAX_SIZE"));
    	List<MatchTicketCommodity> commodityList = new ArrayList<MatchTicketCommodity>();
    	//记录已经处理过的公司
    	String companyType = "";
    	try {
    		 for(Sheet sheet:sheets){
 	        	//得到列数  
 		        int colsNum = sheet.getColumns();
 		        //得到行数  
 	            int rowsNum = sheet.getRows(); 
 	            //单元格  
 	            Cell cell;  
 	            for (int i = 1; i < rowsNum; i++) {//我的excel第一行是标题,所以 i从1开始  
 	            	MatchTicketCommodity matchTicketCommodity = new MatchTicketCommodity();
 	                for (int j = 0; j < colsNum; j++) {  
 	                    cell = sheet.getCell(j, i);//注意:第一个参数是列.第二个参数是行  
 	                    Cell cell0 = sheet.getCell(j, 0);
 	                    if("监控编号".equals(cell0.getContents())){
 	                    	matchTicketCommodity.setMonitorId(cell.getContents());
 	                	}else if("采集页网址".equals(cell0.getContents())){
 	                		matchTicketCommodity.setProductUrl(cell.getContents());
 	                	}else if("监控平台".equals(cell0.getContents())){
 	                		matchTicketCommodity.setCompanyCode(cell.getContents());
 	                	}else if("监控景区".equals(cell0.getContents())){
 	                		matchTicketCommodity.setProductName(cell.getContents());
 	                	}else if("省份".equals(cell0.getContents())){
 	                		matchTicketCommodity.setProvinceCode(cell.getContents());
 	                	}else if("城市".equals(cell0.getContents())){
 	                		matchTicketCommodity.setCityCode(cell.getContents());
 	                	}else if("商品ID".equals(cell0.getContents())){
 	                		matchTicketCommodity.setCommodityId(cell.getContents());
 	                	}else if("商品名称".equals(cell0.getContents())){
 	                		matchTicketCommodity.setCommodityName(cell.getContents());
 	                	}else if("价格".equals(cell0.getContents())){
 	                		matchTicketCommodity.setPrice(cell.getContents());
 	                	}else if("驴妈妈对应商品ID".equals(cell0.getContents())){
 	                		matchTicketCommodity.setLvCommodityId(cell.getContents());
 	                	}else if("支付方式".equals(cell0.getContents())){
 	                		matchTicketCommodity.setPayMode(cell.getContents());
 	                	}else if("是否在线".equals(cell0.getContents())){
 	                		matchTicketCommodity.setOnlineStatus(cell.getContents());
 	                	}
 	                }
 	                //价格不存在，丢弃
 	                if(!StringTools.isValid(matchTicketCommodity.getPrice())){
                     	continue;
                     }
                     //出现UUID重复情况，所以这里用UUID+commodityID,进行MD5加密
                     matchTicketCommodity.setId(MD5Util.encode(UUIDUtil.getUUIDKey()+matchTicketCommodity.getCommodityId()));
                     matchTicketCommodity.setUserId(getCurrentUser(request).getId());
                     matchTicketCommodity.setCreateTime(new Date());
                     //matchTicketCommodity数据预处理 start
                     commodityMatchUtil.preHandelMatchTicketCommodity(matchTicketCommodity);
                     //matchTicketCommodity数据预处理 end
                     //当第一次录入美团商品，会删除当前用户历史录入的美团数据，其他公司相同逻辑
                     companyType = dealHistoryData(companyType,matchTicketCommodity,request);
                     commodityList.add(matchTicketCommodity);
 	               //当内存达到一个临界值时保存一次
 	               if(commodityList.size()==maxSize){
 	            	   dataTotalNumber+=commodityList.size();
 	            	   matchTicketCommodityService.saveList(commodityList);
 	            	   commodityList.clear();
 	            	  
 	               }
 	            } 
 	            //保存完当前sheet
 	            if(commodityList.size()>0){
 	    			dataTotalNumber+=commodityList.size();
 	    			matchTicketCommodityService.saveList(commodityList);
 	    			commodityList.clear();
 	    		}
 	        }
    		 //数据持久化后，按监控平台、监控ID和商品ID去重
    		 deletenumber = matchTicketCommodityService.distinctCommodityData(getCurrentUser(request).getId());
		} catch (Exception e) {
			logger.error(e.getMessage());
			closeInputStream(is);
		}finally {
			closeInputStream(is);
		}
    	logger.info("Excel录入数据"+(dataTotalNumber-deletenumber)+"条，总耗时"+(System.currentTimeMillis()-systemTime)/1000L+"秒！");
    	logger.info("导入数据完毕！>>>>>>>>>>>>>>>"+Thread.currentThread().getId());
    }
    
    /**
     * 根据每列字段名称创建需要导出字段的数组
     * @param headers
     * @return
     */
    public Field[] getFields(String[] headers) {
        Field[] fields=new Field[headers.length];
        MatchTicketCommodity t=new MatchTicketCommodity();
        try {
            for(int i=0;i<headers.length;i++){
                if(headers[i].equals("监控编号")){
                    fields[i]=t.getClass().getDeclaredField("monitorId");
                }else if(headers[i].equals("采集页网址")){
                    fields[i]=t.getClass().getDeclaredField("productUrl");
                }else if(headers[i].equals("监控平台")){
                    fields[i]=t.getClass().getDeclaredField("companyCode");
                }else if(headers[i].equals("监控景区")){
                    fields[i]=t.getClass().getDeclaredField("productName");
                }else if(headers[i].equals("省份")){
                    fields[i]=t.getClass().getDeclaredField("provinceCode");
                }else if(headers[i].equals("城市")){
                    fields[i]=t.getClass().getDeclaredField("cityCode");
                }else if(headers[i].equals("商品ID")){
                    fields[i]=t.getClass().getDeclaredField("commodityId");
                }else if(headers[i].equals("商品名称")){
                    fields[i]=t.getClass().getDeclaredField("commodityName");
                }else if(headers[i].equals("价格")){
                    fields[i]=t.getClass().getDeclaredField("price");
                }else if(headers[i].equals("驴妈妈对应商品ID")){
                    fields[i]=t.getClass().getDeclaredField("lvCommodityId");
                }else if(headers[i].equals("支付方式")){
                    fields[i]=t.getClass().getDeclaredField("payMode");
                }else if(headers[i].equals("是否在线")){
                    fields[i]=t.getClass().getDeclaredField("onlineStatus");
                }
            }
            
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return fields;
    }
    private String dealHistoryData(String companyType, MatchTicketCommodity matchTicketCommodity,
			HttpServletRequest request) {
    	
    	if(!companyType.contains(matchTicketCommodity.getCompanyCode())){
    		//对应公司商品只删除一次
    		companyType+=matchTicketCommodity.getCompanyCode();
			Map<String,String> paramMap = new HashMap<>();
			paramMap.put("userId", getCurrentUser(request).getId());
			paramMap.put("companyCode", matchTicketCommodity.getCompanyCode());
			matchTicketCommodityService.deleteByMap(paramMap);
		}
		return companyType;
	}
    

    @ResponseBody
    @RequestMapping("/batchMatch")
    public Map<String, String> batchMatch(HttpServletRequest request)
    {
    	logger.info("匹配开始！................");
    	long beginTime = System.currentTimeMillis();
    	Map<String, String> result = new HashMap<String, String>();
    	int count = 0;
    	try
    	{
    		Map<String,String> paramMap = new HashMap<>();
    		paramMap.put("userId", getCurrentUser(request).getId());
    		paramMap.put("companyCode", Constant.COMMODITY_AUTO_MATCH_LMM_COMPANY_CODE);
    		//驴妈妈数据
    		List<MatchTicketCommodity> lmmList  = matchTicketCommodityService.findListByMap(paramMap);
    		
    		Map<String,List<MatchTicketCommodity>> monitorMap = new HashMap<String,List<MatchTicketCommodity>>();
    		if(lmmList != null && !lmmList.isEmpty())
    		{
    			
    			String monitorId = null;
    			List<MatchTicketCommodity> list = null;
    			for (MatchTicketCommodity commodity : lmmList)
    			{
    				monitorId = commodity.getMonitorId();
    				list = monitorMap.get(monitorId);
    				if(list == null)
    				{
    					list = new ArrayList<MatchTicketCommodity>();
    					monitorMap.put(monitorId, list);
    				}
    				list.add(commodity);
    			}
    		}
    		//匹配数据
    		paramMap.put("refuseCompanyCode", Constant.COMMODITY_AUTO_MATCH_LMM_COMPANY_CODE);
    		paramMap.remove("companyCode");
    		List<MatchTicketCommodity> matchList  = matchTicketCommodityService.findListByMap(paramMap);
    		if(matchList != null && !matchList.isEmpty())
    		{
    			//存在人工关联关系，默认优先使用人工关联
    			paramMap.put("businessCode", "TICKET");
    			paramMap.put("relType", "1");
    			List<MatchTicketCommodityRel> matchRelList  = matchTicketCommodityRelService.findListByMap(paramMap);
    			Map<String,String> relMap = new HashMap<String,String>();
    			
    			if(matchRelList != null && !matchRelList.isEmpty())
    			{
    				String key = null;
    				String value = null;
    				for (MatchTicketCommodityRel rel : matchRelList)
					{
    					key = rel.getCompanyCode() + rel.getProdId() + rel.getCommodityId();
    					value = rel.getRelCommodityId();
    					if(StringTools.isValid(key) && StringTools.isValid(value))
    					{
    						relMap.put(key, value);
    					}
    					
					}
    			}
    			List<MatchTicketCommodity> commodityList  = new ArrayList<MatchTicketCommodity>();
    			String key = null;
    			List<MatchTicketCommodity> lmmCList = null;
    			for (MatchTicketCommodity commodity : matchList)
    			{
    				key = commodity.getCompanyCode() + commodity.getMonitorId() + commodity.getCommodityId();
    				String lvID = relMap.get(key);
    				lmmCList = monitorMap.get(commodity.getMonitorId());
    				if(lmmCList == null || lmmCList.isEmpty())
    				{
    			    	try {
    			    		
    			    		MatchTicketCommodity realEntity = matchTicketCommodityService.findById(commodity.getId());
    			        	if(realEntity != null)
    			        	{
    			        		realEntity.setLvCommodityId("无关联");
        			        	matchTicketCommodityService.update(realEntity);
    			        	}
    			    		
    					} catch (Exception e) {
    					}
    			    	continue;
    			    	
    				}
    				if(!StringTools.isValid(lvID))
    				{
    					lvID = commodityMatchUtil.maxScore(commodity,lmmCList);
    				}
    				if(StringTools.isValid(lvID))
    				{
    					commodity.setLvCommodityId(lvID);
    					//批量更新
    					count ++;
    					commodityList.add(commodity);
    					if(commodityList.size() == 1000)
    					{
    						matchTicketCommodityService.batchUpdatelvCommodityId(commodityList);
    						commodityList.clear();
    					}
    				}
    				lvID = null;
    			}
    			if(commodityList.size() > 0)
    			{
    				matchTicketCommodityService.batchUpdatelvCommodityId(commodityList);
    			}
    			
    			//消息队列做历史关联关系维护
    			//启动处理历史关联关系的线程
    			
    			result.put("Success", "匹配完成！");
    		}
    	}catch (Exception e)
    	{
    		logger.error("匹配异常",e);
    		result.put("errorMessage", "匹配失败！");
    	}
    	long endTime = System.currentTimeMillis();
    	logger.info("匹配结束！" + "匹配总数count: " + count + "  耗时(ms)： " + (beginTime-endTime));
    	return result;
		
    }
    

    
}
